#include "SGNode.h"

namespace Lame3d
{
	SGNode::SGNode(const std::string &n)
			: name(n), parent(NULL)
	{
	}
	
	SGNode::~SGNode()
	{
		std::map<std::string, SGNode*>::iterator it;
		for(it = children.begin(); it != children.end(); ++it) {
			delete it->second;
		}
	}
	
	const std::string& SGNode::Name() const
	{
		return name;
	}
	
	const CalVector& SGNode::Displacement() const
	{
		return displacement;
	}
	
	CalVector& SGNode::Displacement()
	{
		unsetAbsolute();
		return displacement;
	}
	
	const CalQuaternion& SGNode::Rotation() const
	{
		return rotation;
	}
	
	CalQuaternion& SGNode::Rotation()
	{
		unsetAbsolute();
		return rotation;
	}
	
	void SGNode::AddChild(SGNode *s)
	{
		std::map<std::string, SGNode*>::iterator it;
		it = children.find(s->Name());
		if(it != children.end()) {
			throw "Name conflict when adding SGNode child.";
		} else {
			children[s->Name()] = s;
			s->parent = this;
		}
	}
	
	void SGNode::RemoveChild(const std::string &s)
	{
		std::map<std::string, SGNode*>::iterator it;
		it = children.find(s);
		if(it != children.end()) {
			delete it->second;
			children.erase(it);
		} else {
			throw "Couldn't find name requested for deletion from SGNode.";
		}
	}
	
	SGNode* SGNode::operator[](const std::string &s)
	{
		//printf("me: %s, look: %s\n", name.c_str(), s.c_str());
		if(s == name) {
			return this;
		}
		
		std::string s2 = s.substr(0, 
			s.find_first_of('.') );
		
		std::map<std::string, SGNode*>::iterator it;
		it = children.find(s2);
		if(it == children.end()) {
			return NULL;
		} else {
			std::string s3 = s.substr(s.find_first_of('.')+1);
			return (*it->second)[s3];
		}
	}
	
	void SGNode::MakeAbsolute()
	{
		// I AM ROOT!
		if(parent == NULL) {
			// do nothing.
		} else {
			absoluteDisplacement = displacement;
			absoluteDisplacement *= parent->Rotation();
			absoluteDisplacement += parent->AbsoluteDisplacement();			
		}
		
		// last part!
		_isAbsolute = true;
	}
	
	const CalVector& SGNode::AbsoluteDisplacement()
	{
		if(!isAbsolute()) {
			MakeAbsolute();
		}
		return absoluteDisplacement;
	}
	
	bool SGNode::isAbsolute() const
	{
		return _isAbsolute;
	}
	
	void SGNode::unsetAbsolute()
	{
		_isAbsolute = false;
	}
}

// eof
